import API_MODE from "../service/api/index"
import { API_CONFIG } from "../config"

// const status = {
//   '0': '服务器成功返回请求的数据',
//   '1': '没有数据',

//   '1000': '操作成功（新建、删除、修改数据成功...）',
//   '1001': '操作失败（修改、删除、新建数据失败，微信、百度状态码...）',
//   '-1100': '服务端错误（接口异常、学校中间件请求失败）',

//   '-3000': 'token 失效',
//   '-3001': '该微信没有绑定账号',

//   '-4000': '用户没有开通U米账号',
//   '-4001': 'U米付款失败',
//   '-4002	': 'U米余额不足',

//   '-2000': '响应数据签名错误',
//   '-2001': '微信系统超时，请用相同参数重新调用',
//   '-2002': '非法参数',

//   '-101': '用户不存在钱包',
//   '-102': '余额不足',
//   '-103': '上链失败'
// }

const { devUrl, productionUrl, debug, isDev } = API_CONFIG

const fail = (err, resolve, reject) => {
	wx.showModal({
		title: "接口异常",
		content: `${err.errno}: ${err.errMsg}`,
	})
	// wx.showToast({
	//   title: '接口异常' + err.errMsg,
	//   icon: 'none',
	//   duration: 2000,
	// })
	reject(err.errMsg)
	wx.reportMonitor("1", 1)
}

const success = (res, resolve, reject, requestConfig) => {
	const { data, statusCode } = res
	const { result, errmsg, code, msg } = data
	const version = data.version ? data.version : ""
	if (statusCode === 200) {
		if (code === 200) {
			return resolve(data)
		} else if (code) {
			return reject(msg)
		}
		let errcode = data.errcode
		if (data.errorCode) {
			errcode = data.errorCode
		}
		switch (errcode) {
			case "0":
				if (version) {
					result.version = version
				}
				return resolve(result)
			case "1":
				return resolve({ data: [], errcode: "1" })
			case "0":
				return reject(errmsg)
			// case '3003':
			//   return reject(errcode)
			case "1000":
				return resolve(errmsg, errcode)
			case "9000":
				return resolve({ signature: errmsg })
			// token 异常
			case "1001":
				if (!requestConfig.unAuth && errmsg === "Invalid token") {
					// 重新登陆
					handleLogin.login().then(() => {
						// 防止出现死循环
						if ([null, undefined].includes(requestConfig.reTryLoopCountLimit)) {
							requestConfig.reTryLoopCountLimit = 1
						}
						requestConfig.reTryLoopCountLimit--
						if (requestConfig.reTryLoopCountLimit < 0) {
							reject(errmsg)
							return
						}
						// 重新请求
						sendRequest(requestConfig)
							.then((res) => {
								success(res, resolve, reject, requestConfig)
							})
							.catch((err) => {
								reject(err)
							})
					})
				} else {
					reject(errmsg)
					return
				}
			// 活动配置平台 start
			case "1010":
				return resolve(data)
			case "1011":
				return resolve(data)
			case "1012":
				return resolve(data)
			case "1013":
				return resolve(data)
			case "1014":
				return resolve(data)
			case "1015":
				return resolve(data)
			case "1016":
				return resolve(data)
			// 活动配置平台 end

			case "3004":
				return reject(errmsg)
			case "3003":
				return reject(errmsg)
			case "2003":
				return reject(errmsg)
			case "2004":
				return reject(errmsg)
			case "10011":
				return reject(errmsg)
			case "10012":
				return reject(errmsg)
			case "6001":
				return reject(errmsg)
			case "-1100":
				wx.showToast({
					title: errmsg,
					icon: "none",
					duration: 2000,
				})
				return reject(errmsg)

			case "-3000":
				return reject(errcode)
			case "-3001":
				return reject(errcode)

			case "-4000":
				return reject(errcode)
			case "-4001":
				return reject(errcode)
			case "-4002":
				return reject(errcode)

			case "-2000":
				return reject(errcode)
			case "-2001":
				return reject(errcode)
			case "-2002":
				return reject(errcode)

			case "-101":
				return reject(errcode)
			case "-102":
				return reject(errcode)
			case "-103":
				return reject(errcode)

			default:
				return reject("状态码错误")
		}
	} else if (statusCode >= 500 && statusCode <= 505) {
		wx.reportMonitor("0", 1)
		wx.showToast({
			title: `${statusCode}：服务器错误`,
			icon: "none",
			duration: 2000,
		})
		return reject(`${statusCode}：服务器错误`)
	} else {
		wx.reportMonitor("2", 1)
		reject("statusCode" + statusCode)
	}
}

class MakeApi {
	constructor(options) {
		this.api = {}
		this.apiBuilder(options)
	}
	apiBuilder({ config = {} }) {
		Object.keys(config).map((namespace) => {
			this._apiSingleBuilder({ namespace, config: config[namespace] })
		})
	}
	_apiSingleBuilder({ namespace, config }) {
		config.forEach((item) => {
			let { name, path, baseURL, method } = item
			// 判断当前小程序是否是开发版，开发版取devUrl，体验版和正式版取productionUrl
			if (wx.getAccountInfoSync().miniProgram.envVersion === "develop") {
				baseURL = devUrl
			} else {
				baseURL = productionUrl
			}
			method = method.toUpperCase()
			// 命名空间
			const apiname = `${namespace}/${name}`

			Object.defineProperty(this.api, apiname, {
				value: (outerParams, outerOptions = {}) => {
					return new Promise((resolve, reject) => {
						const token = wx.getStorageSync("token")
						const userInfo = wx.getStorageSync("userInfo")
						const schoolConfig = wx.getStorageSync("schoolConfig")
						const dataParams = Object.assign(
							{
								schoolCode: schoolConfig.schoolCode,
								userId: userInfo.userId,
								// schoolCode: '4144013675',
								// userId: '10007'
							},
							outerParams,
						)
						const requestConfig = Object.assign(
							{
								url: /https?/.test(path) ? path : `${baseURL}${path}`,
								method,
								header: { "X-Authorization": token },
								formData: dataParams,
								data: dataParams,
								apiname,
							},
							outerParams,
							outerOptions,
						)

						if (debug) {
							console.log(`调用接口${apiname}，request参数为`, dataParams)
						}

						if (outerOptions && outerOptions.uploadFile) {
							// 上传文件
							this.uploadFile(requestConfig, resolve, reject)
						} else if (outerOptions && outerOptions.downloadFile) {
							// 下载文件
							this.downloadFile(requestConfig, resolve, reject)
						} else {
							this.request(requestConfig, resolve, reject)
						}
					})
				},
			})
		})
	}
	uploadFile = (requestConfig, resolve, reject) => {
		wx.uploadFile({
			...requestConfig,
			success: (res) => {
				if (res.statusCode === 200) {
					res.data = JSON.parse(res.data)
				}
				if (debug) {
					console.log(
						`调用接口${requestConfig.apiname}，response内容为`,
						res.data,
					)
				}
				success(res, resolve, reject)
			},
			fail: (err) => {
				fail(err, resolve, reject)
			},
		})
	}
	downloadFile = (requestConfig, resolve, reject) => {
		wx.downloadFile({
			...requestConfig,
			success: (res) => {
				if (debug) {
					console.log(
						`调用接口${requestConfig.apiname}，response内容为`,
						res.data,
					)
				}
				success(res, resolve, reject)
			},
			fail: (err) => {
				fail(err, resolve, reject)
			},
		})
	}
	request = (requestConfig, resolve, reject) => {
		wx.request({
			...requestConfig,
			success: (res) => {
				if (debug) {
					console.log(
						`调用接口${requestConfig.apiname}，response内容为`,
						res.data,
					)
				}
				success(res, resolve, reject, requestConfig)
			},
			fail: (err) => {
				console.log(err, "接口报错???!", requestConfig)
				fail(err, resolve, reject)
			},
		})
	}
}

const api = new MakeApi({
	config: API_MODE,
}).api

export default api

// 请求动态生成，无需定义
// config.unAuth 是否不需要登录，不需要登录的接口不需要传token，且不处理token异常的情况
export function sendRequest(config) {
	return new Promise((resolve, reject) => {
		const method = config.method ? config.method.toUpperCase() : "POST"
		let baseURL
		// 判断当前小程序是否是开发版，开发版取devUrl，体验版和正式版取productionUrl
		if (wx.getAccountInfoSync().miniProgram.envVersion === "develop") {
			baseURL = devUrl
		} else {
			baseURL = productionUrl
		}
		//解决url中出现的重复 // 问题
		if (baseURL.endsWith("/") && config.url.startsWith("/")) {
			config.url = config.url.substr(1)
		}
		let url
		//检查是否传进来的是完整的url，如果是则不用拼接 baseUrl
		if (/http?/.test(config.url)) {
			url = config.url
		} else {
			url = baseURL + config.url
		}
		wx.request({
			...config,
			url,
			method,
			header: {
				"X-Authorization": !config.unAuth ? wx.getStorageSync("token") : "",
			},
			success: (res) => {
				resolve(res, url)
			},
			fail: (err) => {
				console.log(err, "接口报错???!", config)
				fail(err, resolve, reject)
			},
		})
	})
}

export function request(config) {
	return new Promise((resolve, reject) => {
		sendRequest(config)
			.then((res, url) => {
				if (debug) {
					console.log(`调用接口${url}，response内容为`, res.data)
				}
				switch (res.data.errcode) {
					case "0":
					case "200":
						resolve(res.data.result)
						break
					// token 异常
					case "1001":
						if (!config.unAuth && res.data.errmsg === "Invalid token") {
							// 重新登陆
							handleLogin.login().then(() => {
								// 防止出现死循环
								if ([null, undefined].includes(config.reTryLoopCountLimit)) {
									config.reTryLoopCountLimit = 1
								}
								config.reTryLoopCountLimit--
								if (config.reTryLoopCountLimit < 0) {
									reject(res.data.errmsg)
									return
								}
								console.log("重新发起请求",config);
								// 重新请求
								request(config).then(resolve).catch(reject)
							})
							break
						}
					default:
						reject(res.data.errmsg)
						break
				}
			})
			.catch((err) => {
				reject(err)
			})
	})
}

export const handleLogin = {
	isLogin: false,
	eventList: [],
	login() {
		return new Promise((resolve, reject) => {
			if (this.isLogin) {
				this.eventList.push({ resolve, reject })
				return
			}
			this.isLogin = true
			const app = getApp()
			app
				.againLogin()
				.then(() => {
					resolve()
					this.eventList.forEach((item) => {
						item.resolve()
					})
					this.eventList = []
				})
				.catch((err) => {
					reject(err)
					this.eventList.forEach((item) => {
						item.reject(err)
					})
					this.eventList = []
				})
				.finally(() => {
					this.isLogin = false
				})
		})
	},
}
